/**
 * 
 */
package io.gitee.falllee.dao.core;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.calcite.linq4j.Enumerable;
import org.apache.calcite.linq4j.Linq4j;
import org.springframework.util.StringUtils;

import io.gitee.falllee.dao.annotation.Column;
import io.gitee.falllee.dao.config.DaoConfigContextHolder;
import io.gitee.falllee.dao.model.BaseDaoConfig;
import io.gitee.falllee.dao.model.DaoConst;
import io.gitee.falllee.dao.util.CommonUtils;
import io.gitee.falllee.dao.util.DaoUtils;
import io.gitee.falllee.dao.util.FilterPlus;
import io.gitee.falllee.kafka.util.KafkaUtils;

/**
 * @author batty
 * @date 2022-07-02
 *
 */
public class BaseBuilder {
    
    protected BaseDaoConfig daoConfig;

    public BaseBuilder(BaseDaoConfig daoConfig) {
        this.daoConfig = daoConfig;
    }
    
    /**
     * 设置enable_flag字段
     * 
     * @param map      参数
     * @param blSelect 是否查询
     */
    protected void setEnableFlag(Map<String, Object> map, boolean blSelect) {
        if (blSelect && DaoConfigContextHolder.getIncludeDisable()) {
            return;
        }
        String enableFlagFieldName = daoConfig.getEnableFlag();
        String enableFlagValue = daoConfig.getEnableFlagValue();
        if (StringUtils.hasLength(enableFlagFieldName) && StringUtils.hasLength(enableFlagValue)) {
            String[] strs = enableFlagValue.split(DaoConst.COMMA);
            if (StringUtils.hasLength(strs[0])) {
                map.put(DaoConst.ENABLE_FLAG, getQuoteField(enableFlagFieldName));
                map.put(DaoConst.ENABLE_FLAG_VALUE, DaoUtils.getEnableFlagValue(strs[0]));
                if (strs.length > 1) {
                    map.put(DaoConst.ENABLE_FLAG_VALUE_NO, DaoUtils.getEnableFlagValue(strs[1]));
                }
            }
        }
    }
    
    /**
     * 设置失效条件
     * 
     * @param map
     */
    protected void setEnableFlagInvalid(Map<String, Object> map) {
        String enableFlagFieldName = daoConfig.getEnableFlag();
        String enableFlagValue = daoConfig.getEnableFlagValue();
        if (StringUtils.hasLength(enableFlagFieldName) && StringUtils.hasLength(enableFlagValue)) {
            String[] strs = enableFlagValue.split(DaoConst.COMMA);
            if (StringUtils.hasLength(strs[0])) {
                map.put(DaoConst.ENABLE_FLAG, getQuoteField(enableFlagFieldName));
                map.put(DaoConst.ENABLE_FLAG_VALUE, DaoUtils.getEnableFlagValue(strs[1]));
            }
        }
    }
    
    /**
     * 设置同步时间
     * 
     * @param map
     * @param syncDateField
     * @param syncDatePrecision
     */
    protected void setSyncDate(Map<String, Object> map, String syncDateField, Integer syncDatePrecision) {
        if (StringUtils.hasLength(syncDateField)) {
            map.put(DaoConst.SYNC_DATE, syncDateField);
        }
        if (syncDatePrecision > 0) {
            map.put(DaoConst.SYNC_DATE_PRECISION, syncDatePrecision);
        }
    }
    
    protected String getColumnValue(Column col) {
        if (col == null) {
            return "";
        }
        String val = col.value();
        return daoConfig.getValue(val);
    }

    protected String getParamName() {
        return String.format("P_%s", CommonUtils.getGuid().replace("-", ""));
    }

    
    protected String getQuoteField(String columnName) {
        String quotes = daoConfig.getQuotes();
        return String.format(DaoConst.FORMAT_THREEE, quotes, columnName, quotes);
    }
    
    protected List<String> getComponentConfigFields(boolean blSyncTable, String syncDateField) {
        List<String> configFields = new ArrayList<>();
        // 非同步表需要获取组件级固定字段过滤在sql层赋值；同步表则来源实体本身的值
        if (!blSyncTable) {
            return daoConfig.getComponentConfigFields();
        }
        // 如果是同步表，则添加同步字段作为固定字段，在sql直接赋值
        if (StringUtils.hasLength(syncDateField)) {
            configFields.add(syncDateField);
        }
        return configFields;
    }
    
    protected Enumerable<Method> getValidateMethods(Method[] methods, List<String> configFields) {
        return Linq4j.asEnumerable(methods).where(p -> {
            Column col = p.getAnnotation(Column.class);
            String columnName = getColumnValue(col);
            if (!StringUtils.hasLength(columnName)) {
                return false;
            }
            if (col.key()) {
                return true;
            }
            // 排除组件级的配置字段如创建人、创建时间等字段，sql会自动处理
            if (configFields.contains(columnName.toLowerCase())) {
                return false;
            }
            // 排除非映射字段
            return col.map();
        });
    }

    /**
     * 获取参数表达式
     * 
     * @param columnName
     * @return
     */
    protected String getParamExpression(String columnName) {
        return String.format("%s=#{%s}", getQuoteField(columnName), columnName);
    }

    /**
     * 获取参数表达式
     * 
     * @param columnName
     * @param paramName
     * @return
     */
    protected String getParamExpression(String columnName, String paramName) {
        return String.format("%s=#{%s}", getQuoteField(columnName), paramName);
    }

    protected String getKeyListFilter(List<? extends Object> keyValueList, String keyField, Map<String, Object> map) {
        FilterPlus filterPlus = FilterPlus.build().addIn(keyField, keyValueList);
        map.putAll(filterPlus.getParamMap());
        return filterPlus.getParamFilter();
    }
    
    /**
     * 获取配置的topic（优先从dao.properites取，如果取不到再从application.yml取）
     * 
     * @return 配置topic
     */
    protected String getConfigTopic() {
        String topic = daoConfig.getTopic();
        if (!StringUtils.hasLength(topic)) {
            topic = KafkaUtils.getDefaultTopic();
        }
        return topic;
    }
}
